#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
彩票助手定时任务模块
实现自动数据更新功能
"""

import schedule
import time
import threading
from datetime import datetime, timedelta
import logging
from modules.crawler import LotteryCrawler
from modules.database import DatabaseManager

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('scheduler.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

class LotteryScheduler:
    """彩票数据定时更新调度器"""
    
    def __init__(self):
        self.db_manager = DatabaseManager()
        self.crawler = LotteryCrawler(self.db_manager)
        self.running = False
        self.scheduler_thread = None
        
    def update_ssq_data(self):
        """更新双色球数据"""
        try:
            logger.info("开始更新双色球数据...")
            
            # 获取最新期号
            latest_period = self.crawler.get_latest_period('ssq')
            logger.info(f"双色球最新期号: {latest_period}")
            
            # 爬取最新数据（这里使用模拟数据）
            success_count = self.crawler.crawl_mock_data('ssq', 1)
            
            if success_count > 0:
                logger.info(f"双色球数据更新成功，新增 {success_count} 条记录")
            else:
                logger.warning("双色球数据更新失败或无新数据")
                
        except Exception as e:
            logger.error(f"更新双色球数据时发生错误: {str(e)}")
    
    def update_dlt_data(self):
        """更新大乐透数据"""
        try:
            logger.info("开始更新大乐透数据...")
            
            # 获取最新期号
            latest_period = self.crawler.get_latest_period('dlt')
            logger.info(f"大乐透最新期号: {latest_period}")
            
            # 爬取最新数据（这里使用模拟数据）
            success_count = self.crawler.crawl_mock_data('dlt', 1)
            
            if success_count > 0:
                logger.info(f"大乐透数据更新成功，新增 {success_count} 条记录")
            else:
                logger.warning("大乐透数据更新失败或无新数据")
                
        except Exception as e:
            logger.error(f"更新大乐透数据时发生错误: {str(e)}")
    
    def update_all_data(self):
        """更新所有彩票数据"""
        logger.info("开始执行定时数据更新任务...")
        self.update_ssq_data()
        self.update_dlt_data()
        logger.info("定时数据更新任务完成")
    
    def cleanup_old_data(self):
        """清理过期数据（保留最近1000期）"""
        try:
            logger.info("开始清理过期数据...")
            
            # 清理双色球过期数据
            ssq_deleted = self.db_manager.cleanup_old_records('ssq', keep_count=1000)
            logger.info(f"清理双色球过期数据 {ssq_deleted} 条")
            
            # 清理大乐透过期数据
            dlt_deleted = self.db_manager.cleanup_old_records('dlt', keep_count=1000)
            logger.info(f"清理大乐透过期数据 {dlt_deleted} 条")
            
            logger.info("数据清理任务完成")
            
        except Exception as e:
            logger.error(f"清理过期数据时发生错误: {str(e)}")
    
    def backup_database(self):
        """备份数据库"""
        try:
            logger.info("开始数据库备份...")
            
            backup_file = f"backup_lottery_{datetime.now().strftime('%Y%m%d_%H%M%S')}.db"
            success = self.db_manager.backup_database(backup_file)
            
            if success:
                logger.info(f"数据库备份成功: {backup_file}")
            else:
                logger.error("数据库备份失败")
                
        except Exception as e:
            logger.error(f"数据库备份时发生错误: {str(e)}")
    
    def setup_schedules(self):
        """设置定时任务"""
        # 每天晚上9点更新数据（双色球和大乐透通常在晚上开奖）
        schedule.every().day.at("21:00").do(self.update_all_data)
        
        # 每周日凌晨2点清理过期数据
        schedule.every().sunday.at("02:00").do(self.cleanup_old_data)
        
        # 每月1号凌晨3点备份数据库
        schedule.every().month.do(self.backup_database)
        
        # 测试用：每5分钟更新一次数据（可根据需要调整）
        # schedule.every(5).minutes.do(self.update_all_data)
        
        logger.info("定时任务设置完成:")
        logger.info("- 每天21:00更新彩票数据")
        logger.info("- 每周日02:00清理过期数据")
        logger.info("- 每月1号03:00备份数据库")
    
    def run_scheduler(self):
        """运行调度器"""
        logger.info("定时任务调度器启动")
        
        while self.running:
            try:
                schedule.run_pending()
                time.sleep(60)  # 每分钟检查一次
            except Exception as e:
                logger.error(f"调度器运行时发生错误: {str(e)}")
                time.sleep(60)
        
        logger.info("定时任务调度器停止")
    
    def start(self):
        """启动定时任务"""
        if self.running:
            logger.warning("定时任务已在运行中")
            return
        
        self.running = True
        self.setup_schedules()
        
        # 在单独线程中运行调度器
        self.scheduler_thread = threading.Thread(target=self.run_scheduler, daemon=True)
        self.scheduler_thread.start()
        
        logger.info("定时任务启动成功")
    
    def stop(self):
        """停止定时任务"""
        if not self.running:
            logger.warning("定时任务未在运行")
            return
        
        self.running = False
        
        if self.scheduler_thread and self.scheduler_thread.is_alive():
            self.scheduler_thread.join(timeout=5)
        
        # 清除所有定时任务
        schedule.clear()
        
        logger.info("定时任务停止成功")
    
    def get_next_runs(self):
        """获取下次执行时间"""
        jobs = schedule.get_jobs()
        next_runs = []
        
        for job in jobs:
            next_run = job.next_run
            if next_run:
                next_runs.append({
                    'job': str(job.job_func.__name__),
                    'next_run': next_run.strftime('%Y-%m-%d %H:%M:%S')
                })
        
        return next_runs
    
    def run_manual_update(self):
        """手动执行数据更新"""
        logger.info("手动执行数据更新...")
        self.update_all_data()

def main():
    """主函数"""
    logger.info("=== 彩票数据定时任务模块 ===")
    
    scheduler = LotteryScheduler()
    
    logger.info("定时任务执行计划:")
    logger.info("- 每天 09:00, 15:00, 21:30 自动更新数据")
    logger.info("- 每周日 02:00 清理过期数据")
    logger.info("- 每月1日 03:00 备份数据库")
    logger.info("- 手动更新: python scheduler.py --update")
    
    if len(sys.argv) > 1 and sys.argv[1] == '--update':
        logger.info("执行手动数据更新...")
        scheduler.update_lottery_data()
    else:
        try:
            scheduler.start()
            logger.info("定时任务已启动，按 Ctrl+C 停止")
            
            # 保持程序运行
            while True:
                time.sleep(1)
                
        except KeyboardInterrupt:
            logger.info("收到停止信号，正在关闭定时任务...")
            scheduler.stop()
            logger.info("定时任务已停止")
        except Exception as e:
            logger.error(f"定时任务运行出错: {e}")
            scheduler.stop()

if __name__ == '__main__':
    main()